A driver can be unloaded either because all its devices are closed and a timeout has elapsed, or because the operator has used the ml command (see the ml(1) reference page). The kernel does not unload a driver unless the driver provides a pfxunload() entry point. Without this entry point, the driver can be dynamically loaded, but then remains in memory.int pfxunload(void);
It is not easy to retain state information about the device over the time when the driver is not in memory. The entire text and data of a loadable driver, including static variables, are removed and reloaded. Only global variables defined in the descriptive file (see "Describing the Driver in /var/sysgen/master.d") remain in memory after the driver is unloaded. Be sure not to store any addresses of driver code or driver static variables in global variables, since these addresses will be different when the driver is reloaded.
The driver may have allocated dynamic memory. This should be released, because the addresses of allocated memory will be lost when the driver is unloaded, and more will be allocated if the driver is reloaded. For example, the driver should use phfree() to release a pollhead structure allocated by phalloc() (see "Use and Operation of poll(2)", and the phalloc(D3) and phfree(D3) reference pages). It is also the time to release any PIO maps using pio_mapfree() (see "Mapping PIO Addresses"), and to release any process handles (see "Sending a Process Signal").
The driver is not required to unload. If the driver should not be unloaded at this time, it returns a nonzero return code to the call, and the kernel does not unload it. There are several reasons why a driver should not be unloaded.
The kernel calls pfxunload() only when no device special files managed by the driver are open. If any device had been opened, the pfxclose() entry has been called. However, if any device was mapped through the pfxmap() entry, the mapping could still exist. If the driver has any resources tied up in association with a memory mapping, it should return a nonzero value to the pfxunload call.
A driver should never permit unloading when there is any kind of pointer to the driver held in any kernel data structure. It is a frequent design error to unload when there is a live pointer to the driver. Unpredictable kernel panics often result.
One example of a live pointer to a driver is a pending callback function. Any pending itimeout() or bufcall() timers should be cancelled before returning 0 from pfxunload(). A driver for the EISA or GIO bus can register an interrupt handler. There is no way to retract the registration of an EISA interrupt handler (see "Allocating and Programming an IRQ"), so an EISA driver should never permit unloading once an IRQ has been programmed. A GIO driver is able to unregister an interrupt handler (see "GIO-Specific Kernel Functions"), and must do so before it permits unloading.